package ru.evga.inse.core.dao;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.ParameterExpression;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Root;

import ru.evga.inse.core.domain.BaseEntity;


public class FindRangeContext<E extends BaseEntity>
{
    private List<Parameter> parameters;
    private IDao<Long, E> dao;
    private CriteriaQuery<E> criteriaQuery;
    private Root<E> root;

    public FindRangeContext(IDao<Long, E> dao)
    {
        this.dao = dao;
        this.criteriaQuery = dao.crateCriteriaQuery();
        this.parameters = new LinkedList<Parameter>();
        this.root = criteriaQuery.from(dao.getEntityClass());
    }

    public void setOrder(final String orderBy, final Boolean isAsc)
        throws DaoException
    {
        if (orderBy != null && !orderBy.equals(""))
        {
            dao.assertEntityHasField(orderBy);
            Path<?> path = root.get(orderBy);
            if (isAsc != null && isAsc)
            {
                criteriaQuery.orderBy(dao.getCriteriaBuilder().asc(path));
            }
            else
            {
                criteriaQuery.orderBy(dao.getCriteriaBuilder().desc(path));
            }
        }
    }

    public void addLike(String field, String value)
    {
        String parameterName = field + "Parameter";
        ParameterExpression<String> p = dao.getCriteriaBuilder().parameter(String.class,
            parameterName);
        criteriaQuery.where(dao.getCriteriaBuilder().like(root.<String> get(field), p));
        parameters.add(new Parameter(parameterName, value));
    }

    public CriteriaQuery<E> getCriteriaQuery()
    {
        return this.criteriaQuery;
    }

    public List<Parameter> getParameters()
    {
        return Collections.unmodifiableList(parameters);
    }
    
    public TypedQuery<E> cretaeQuery()
    {
        return dao.getEntityManager().createQuery(this.criteriaQuery);

    }
}
